package com.lfy.modules.common.utils;

import cn.hutool.extra.spring.SpringUtil;
import com.lfy.modules.common.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Objects;
/**
 *  request相关的工具类
 *
 * @author <a href="https://www.lvfeiy.top">lvfeiyang</a>
 * @date 2024/4/25 0:59
 */
@Slf4j
public class RequestUtil {
    public static final String LOCAL_REMOTE_HOST1 = "0:0:0:0:0:0:0:1";
    public static final String LOCAL_REMOTE_HOST2 = "127.0.0.1";
    public static final String LOCAL_REMOTE_HOST3 = "localhost";
    public static final String LOCAL_REMOTE_HOST4 = "unknown";

    private static Searcher searcher;
    private static Environment env;
    static {
        Resource resource = new ClassPathResource("ip/ip2region.xdb");
        byte[] cBuff;
        try(InputStream inputStream = resource.getInputStream()) {
             cBuff = StreamUtils.copyToByteArray(inputStream);
            searcher = Searcher.newWithBuffer(cBuff);
        } catch (Exception e) {
            log.error(" com.lfy.modules.common.utils.RequestUtil: load xdb file error", e);
        }
        env = SpringUtil.getBean(Environment.class);
    }

    /**
     * 归属地获取
     * @param ip ip
     * @return String
     */
    public static String getPlace(String ip) {
        if (StringUtils.isEmpty(ip) || LOCAL_REMOTE_HOST4.equals(ip)) {
            return "未知";

        } else if (LOCAL_REMOTE_HOST1.equals(ip) || LOCAL_REMOTE_HOST2.equals(ip)) {
            return "本地";
        }
        try {
            String addr = searcher.searchByStr(ip);
            log.info(" com.lfy.modules.common.utils.RequestUtil.getPlace(): ip:{}, 归属地:{}", ip, addr);
            return addr;
        } catch (Exception e) {
            log.error(" com.lfy.modules.common.utils.RequestUtil :search ip error ip:{}, e:{}", ip,e);
        }
        return "未知";
    }

    public static RequestAttributes getRequestAttributes() {
        return RequestContextHolder.getRequestAttributes();
    }

    public static HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (!Objects.isNull(requestAttributes)) {
            return requestAttributes.getRequest();
        }
        return null;
    }

    public static String getIpAddress() {
        HttpServletRequest request = getRequest();
        if (Objects.isNull(request)) {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip == null) {
            ip = "unknown";
        }
        return ip;
    }

    public static String getIpAddress(HttpServletRequest request) {

        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || LOCAL_REMOTE_HOST4.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip == null) {
            ip = "unknown";
        }
        return ip;
    }
    public static String getUri(){
        HttpServletRequest request = getRequest();
        if (!Objects.isNull(request)) {
            return request.getRequestURI();
        }
        return null;

    }
    public static String getNginxRealIp() {
        HttpServletRequest request = getRequest();
        if (!Objects.isNull(request)) {

            return request.getHeader("X-Real-IP");
        }
        return LOCAL_REMOTE_HOST4;
    }
    public static String getLimitIpKey( ) {
        if(env.acceptsProfiles(Profiles.of("dev", "test"))){
            return getIpAddress().concat("@")+getUri();
        }
        return getNginxRealIp().concat("@")+getUri();
    }
    public static String getIp( ) {
        if(env.acceptsProfiles(Profiles.of("dev", "test"))){
            return getIpAddress();
        }
        return getNginxRealIp();
    }

    public static void writeResponse(R<Void> error, ServletResponse servletResponse) {
        servletResponse.setContentType("application/json;charset=UTF-8");
        try {
            String result = JsonUtils.toStr(error);
            servletResponse.getWriter().write(result);
        } catch (Exception e) {
            log.error(" com.lfy.modules.common.utils.RequestUtil: write response error", e);
        }
    }
}
